 /*******************************************************************************
  * Copyright (c) 2003, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.osgi.internal.resolver;

 import java.util.*;
 import org.eclipse.osgi.framework.internal.core.Constants;
 import org.eclipse.osgi.service.resolver.*;

 public class ImportPackageSpecificationImpl extends VersionConstraintImpl implements ImportPackageSpecification {
     private String resolution = ImportPackageSpecification.RESOLUTION_STATIC; // the default is static
 private String symbolicName;
     private VersionRange bundleVersionRange;
     private Map attributes;

     public Map getDirectives() {
         Map result = new HashMap(5);
         if (resolution != null)
             result.put(Constants.RESOLUTION_DIRECTIVE, resolution);
         return result;
     }

     public Object getDirective(String key) {
         if (key.equals(Constants.RESOLUTION_DIRECTIVE))
             return resolution;
         return null;
     }

     public Object setDirective(String key, Object value) {
         if (key.equals(Constants.RESOLUTION_DIRECTIVE))
             return resolution = (String ) value;
         return null;
     }

     public void setDirectives(Map directives) {
         if (directives == null)
             return;
         resolution = (String ) directives.get(Constants.RESOLUTION_DIRECTIVE);
     }

     public String getBundleSymbolicName() {
         return symbolicName;
     }

     public VersionRange getBundleVersionRange() {
         if (bundleVersionRange == null)
             return VersionRange.emptyRange;
         return bundleVersionRange;
     }

     public Map getAttributes() {
         return attributes;
     }

     public boolean isSatisfiedBy(BaseDescription supplier) {
         if (!(supplier instanceof ExportPackageDescription))
             return false;
         ExportPackageDescriptionImpl pkgDes = (ExportPackageDescriptionImpl) supplier;

         // If we are in strict mode, check to see if the export specifies friends.
 // If it does, are we one of the friends
 String [] friends = (String []) pkgDes.getDirective(Constants.FRIENDS_DIRECTIVE);
         Boolean internal = (Boolean ) pkgDes.getDirective(Constants.INTERNAL_DIRECTIVE);
         if (internal.booleanValue() || friends != null) {
             boolean strict = ((StateImpl) getBundle().getContainingState()).inStrictMode();
             if (strict) {
                 if (internal.booleanValue())
                     return false;
                 boolean found = false;
                 if (friends != null && getBundle().getSymbolicName() != null)
                     for (int i = 0; i < friends.length; i++)
                         if (getBundle().getSymbolicName().equals(friends[i]))
                             found = true;
                 if (!found)
                     return false;
             }
         }

         if (symbolicName != null) {
             BundleDescription exporter = pkgDes.getExporter();
             if (!symbolicName.equals(exporter.getSymbolicName()))
                 return false;
             if (getBundleVersionRange() != null && !getBundleVersionRange().isIncluded(exporter.getVersion()))
                 return false;
         }

         String name = getName();
         // shortcut '*'
 // NOTE: wildcards are supported only in cases where this is a dynamic import
 if (!"*".equals(name) && !(name.endsWith(".*") && pkgDes.getName().startsWith(name.substring(0, name.length() - 1))) && !pkgDes.getName().equals(name)) //$NON-NLS-1$ //$NON-NLS-2$
 return false;
         if (getVersionRange() != null && !getVersionRange().isIncluded(pkgDes.getVersion()))
             return false;

         Map importAttrs = getAttributes();
         if (importAttrs != null) {
             Map exportAttrs = pkgDes.getAttributes();
             if (exportAttrs == null)
                 return false;
             for (Iterator i = importAttrs.keySet().iterator(); i.hasNext();) {
                 String importKey = (String ) i.next();
                 Object importValue = importAttrs.get(importKey);
                 Object exportValue = exportAttrs.get(importKey);
                 if (exportValue == null || !importValue.equals(exportValue))
                     return false;
             }
         }
         String [] mandatory = (String []) pkgDes.getDirective(Constants.MANDATORY_DIRECTIVE);
         if (mandatory != null) {
             for (int i = 0; i < mandatory.length; i++) {
                 if (Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE.equals(mandatory[i])) {
                     if (symbolicName == null)
                         return false;
                 } else if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(mandatory[i])) {
                     if (bundleVersionRange == null)
                         return false;
                 } else if (Constants.PACKAGE_SPECIFICATION_VERSION.equals(mandatory[i]) || Constants.VERSION_ATTRIBUTE.equals(mandatory[i])) {
                     if (getVersionRange() == null)
                         return false;
                 } else { // arbitrary attribute
 if (importAttrs == null)
                         return false;
                     if (importAttrs.get(mandatory[i]) == null)
                         return false;
                 }
             }
         }
         // finally check the ee index
 if (((BundleDescriptionImpl)getBundle()).getEquinoxEE() < 0)
             return true;
         int eeIndex = ((Integer ) pkgDes.getDirective(ExportPackageDescriptionImpl.EQUINOX_EE)).intValue();
         return eeIndex < 0 || eeIndex == ((BundleDescriptionImpl)getBundle()).getEquinoxEE();
     }

     protected void setBundleSymbolicName(String symbolicName) {
         this.symbolicName = symbolicName;
     }

     protected void setBundleVersionRange(VersionRange bundleVersionRange) {
         this.bundleVersionRange = bundleVersionRange;
     }

     protected void setAttributes(Map attributes) {
         this.attributes = attributes;
     }

     public String toString() {
         return "Import-Package: " + getName() + "; version=\"" + getVersionRange() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 }
 }

